﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using EnvRide.Core.ObjectModel;
using CodeMadeSimple.Common.Tests;
using System.Xml;
using CodeMadeSimple.PropertiesManagement;

namespace EnvRide.Core.UnitTests
{
    [TestFixture]
    public class ElementOverrideIncludeTests : OverrideIncludeTests<ElementOverrideInclude>
    {
        private const string FILE_PATH = "ElementOverrideIncludeTests.xml";

        [Test]
        public void Process()
        {
            EnvRide.Core.ObjectModel.Environment env = Helper.CreateDummyEnvironment();
            env.IncludedElementOverrides = new ElementOverrideIncludeCollection();

            ElementOverrideInclude elemOverInc = new ElementOverrideInclude();
            elemOverInc.Environment = env;
            elemOverInc.Project = env.Project;

            env.IncludedElementOverrides.Add(elemOverInc);

            ExceptionAssert.AssertNullArgumentException("args", () => elemOverInc.Process(null));

            XmlDocument doc = new XmlDocument();
            doc.Load(FILE_PATH);

            EnvRideProcessArguments args = new EnvRideProcessArguments { Document = doc };

            elemOverInc.FilePath = "SubFolder\\FileToInclude.envRide";
            elemOverInc.EnvironmentName = "EnvToInclude1";

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><includedElem5 /><includedElem6 /><includedElem3 /><includedElem4 /><includedElem1 /><includedElem2 /></root>", doc.OuterXml);

            doc.Load(FILE_PATH);

            elemOverInc.OverrideName = "ElemOver1";

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><includedElem1 /></root>", doc.OuterXml);

            elemOverInc.OverrideName = "ElemOver1,ElemOver3";

            doc.Load(FILE_PATH);

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><includedElem1 /><includedElem3 /></root>", doc.OuterXml);

            elemOverInc.OverrideName = "ElemOver3,ElemOver1";
            
            doc.Load(FILE_PATH);

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><includedElem3 /><includedElem1 /></root>", doc.OuterXml);

            doc.Load(FILE_PATH);

            elemOverInc.OverrideName = "ElemOver1,ElemOver5,ElemOver3";

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><includedElem1 /><includedElem5 /><includedElem3 /></root>", doc.OuterXml);

            elemOverInc.EnvironmentName = "EnvWithProperty";
            elemOverInc.OverrideName = "ElemWithProp";

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            elemOverInc.Process(args);

            AssertHasErrors(args, new[] { GetPropertyContainerNullMessage() });

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><elemWithProp>${Prop}</elemWithProp></root>", doc.OuterXml);

            PropertyContext ctx = new PropertyContext("Ctx");
            ctx.AddProperty(new Property { Name = "Prop", Value = "PropValue" });
            ctx.AddProperty(new Property { Name = "CurrentFolder", Value = ".\\" });

            elemOverInc.FilePath = "${CurrentFolder}\\" + elemOverInc.FilePath;

            args.PropertyContainer = ctx;

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            args.HasErrors = false;

            elemOverInc.Process(args);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><elemWithProp>PropValue</elemWithProp></root>", doc.OuterXml);

            PropertyContext relatedCtx = new PropertyContext("Related");
            relatedCtx.AddProperty(new Property { Name = "Prop", Value = "RelatedValue" });

            ctx.AddRelationship("Related", relatedCtx);

            elemOverInc.PropertiesPrefix = ">Related:";

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            Assert.IsNull(args.PropertiesPrefix);

            elemOverInc.Process(args);

            Assert.IsNull(args.PropertiesPrefix, ARGS_PROPS_PFX_RET_TO_PREV_VALUE_MSG);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><elemWithProp>RelatedValue</elemWithProp></root>", doc.OuterXml);
                        
            elemOverInc.PropertiesPrefix = null;

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            Assert.IsNull(args.PropertiesPrefix);

            elemOverInc.Process(args);

            Assert.IsNull(args.PropertiesPrefix, ARGS_PROPS_PFX_RET_TO_PREV_VALUE_MSG);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><elemWithProp>PropValue</elemWithProp></root>", doc.OuterXml);

            elemOverInc.NewPropertyContainer = ">Related";

            args.HasErrors = false;

            Appender.Clear();

            doc.Load(FILE_PATH);

            Assert.IsNull(args.PropertiesPrefix);

            Assert.AreSame(ctx, args.PropertyContainer);

            elemOverInc.Process(args);

            Assert.IsNull(args.PropertiesPrefix, ARGS_PROPS_PFX_RET_TO_PREV_VALUE_MSG);

            Assert.AreSame(ctx, args.PropertyContainer);

            AssertHasNoErrors(args);

            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><elemWithProp>RelatedValue</elemWithProp></root>", doc.OuterXml);

            ProcessWithErrors(FILE_PATH, elemOverInc, doc, args);
        }

        [Test]
        public void Validate()
        {
            ElementOverrideInclude elemOverInc = new ElementOverrideInclude();

            Validate(elemOverInc);
        }
    }
}
